package code.google.jcontainer.annotation;

import code.google.jcontainer.invoke.AnnotationResolverInvocationHandler;
import code.google.jcontainer.invoke.InvocationHandler;
import code.google.jcontainer.invoke.MethodInvocationHandler;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Annotation used to declare a Container class
 *
 * @author <a href="mailto:jfox.young@gmail.com">Young Yang</a>
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Container {

    /**
     * Container name, used to get this container by {@link code.google.jcontainer.ContainerFactory#getContainer(String)}
     */
    String name();

    /**
     * annotation type of component managed by this container 
     */
    Class<? extends Annotation> componentType();

    /**
     * supported annotations, these annotations will be parsed by this container
     * This annotation should be annotated by @Resolve to define its resolveClass and when to resolve
     * for example, take a look at the embedded annotation {@link code.google.jcontainer.support.log.Log Log}
     */
    Class<? extends Annotation>[] supportAnnotations() default {};

    /**
     * for those Annotations defined by third parties, use this method to specify resolver
     * example:
     * \@Container(resolveAnnotations={
     *           \@Resolve(
     *                            annotationClass=EJB.class,
     *                            resolverClass=EJBAnnotationResolver.class,
     *                            when={Resolve.WHEN.AFTER_CONSTRUCT})
     * })
     */
    Resolve[] resolveAnnotations() default {};

    /**
     * Define InvocationHandles, will invoke one by one
     * NOTE: AnnotationResolverInvocationHandler and MethodInvocationHandler should be the last ones
     */
    Class<? extends InvocationHandler>[] invocationHandlers() default {AnnotationResolverInvocationHandler.class, MethodInvocationHandler.class};

    /**
     * true to use CGLIB to enhancer component, false to use JDK dynamic proxy
     */
    boolean useCGLIB() default true;

}
